﻿using Microsoft.AspNetCore.Mvc;
using SXFramWork.Core;
using SXFramWork.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace SXFramWork.API
{
    /// <summary>
    /// 程序初始化
    /// </summary>
    public class ApplicationHelper
    {
        /// <summary>
        /// 控制器方法
        /// </summary>
        public static ConcurrentDictionary<string, MethodInfo> dll_controller_action { get; private set; }
        /// <summary>
        /// 菜单权限列表
        /// </summary>
        public static ConcurrentDictionary<string, MenuAttribute> hasMenu = new ConcurrentDictionary<string, MenuAttribute>();
        /// <summary>
        /// 按钮执行权限列表
        /// </summary>
        public static ConcurrentDictionary<string, PowerAttribute> hasPower = new ConcurrentDictionary<string, PowerAttribute>();
        /// <summary>
        /// API执行权限列表
        /// </summary>
        public static ConcurrentDictionary<string, ApiPowerAttribute> hasApiPower = new ConcurrentDictionary<string, ApiPowerAttribute>();

        /// <summary>
        /// 系统第一次启动的时候调用
        /// </summary>
        public static async Task Init(Type _parse_type)
        {
            //初始化菜单和权限
           await InitMenupower(_parse_type);
        }
        /// <summary>
        /// 初始化菜单和权限
        /// </summary>
        /// <param name="_parse_type"></param>
        public static async Task InitMenupower(Type _parse_type)
        {
                var types = _parse_type.Assembly.GetTypes();
                //遍历所有类
                foreach (var type in types)
                {
                    Type classType = type;
                    string className = classType.Name.ToLower();
                    if (!className.EndsWith("controller")|| (className == "_parse_controller")) continue;
                   
                    //遍历所有方法
                    MethodInfo[] methods = classType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
                    if (methods == null) continue;

                    //控制器名称
                    string strcontroller = type.Name.ToLower();
                    strcontroller = strcontroller.Replace("controller", "");

                    //控制器的Area
                    object[] attributesArea = classType.GetCustomAttributes(typeof(AreaAttribute), true);
                    var areaStr = "";
                    if (attributesArea != null && attributesArea.Length == 1)
                    {
                        AreaAttribute area = attributesArea[0] as AreaAttribute;
                        areaStr = area.RouteValue.ToLower();
                    }


                foreach (var method in methods)//遍历方法
                    {
                        var httpMethodeStr = "post";
                        object[] attributesmenu = method.GetCustomAttributes(typeof(MenuAttribute), true);
                        object[] attributespower = method.GetCustomAttributes(typeof(PowerAttribute), true);
                        object[] attributesapipower = method.GetCustomAttributes(typeof(ApiPowerAttribute), true);
                        object[] attributesHttpget = method.GetCustomAttributes(typeof(HttpGetAttribute), true);
                        //object[] attributesHttppost = method.GetCustomAttributes(typeof(HttpPostAttribute), true);
                        if (attributesHttpget != null && attributesHttpget.Length == 1)
                        {
                            httpMethodeStr = "get";
                        }
                       //菜单权限
                       if (attributesmenu != null && attributesmenu.Length == 1)
                        {
                           
                            MenuAttribute _atmenu = attributesmenu[0] as MenuAttribute;
                            //菜单编号
                            _atmenu.Code = areaStr +"_"+ strcontroller + "_" + method.Name.ToLower()/*+"_"+httpMethodeStr*/;
                        //菜单路径
                        if (_atmenu.MenuUrl == "")
                            //菜单页面路径
                            _atmenu.MenuUrl = "/" + areaStr + "/" + strcontroller;/*+"/"+method.Name.ToLower();*/

                            //判断是否重复
                            if (hasMenu.ContainsKey(_atmenu.Code.ToLower()))
                            {
                                throw new Exception("存在相同的菜单Code:" + _atmenu.Code + ",两个名称是:" + _atmenu.Title + "/" + (hasMenu[_atmenu.Code] as MenuAttribute).Title);
                            }

                            hasMenu[_atmenu.Code.ToLower()] = _atmenu;
                         }
                        //按钮执行权限
                        if (attributespower != null && attributespower.Length == 1)
                        {
                            PowerAttribute _atpower = attributespower[0] as PowerAttribute;
                            //权限编号
                            _atpower.Code = areaStr +"_"+ strcontroller + "_" + method.Name.ToLower()/*+"_"+httpMethodeStr*/;
                            
                            
                            
                            //判断是否重复
                            if (hasPower.ContainsKey(_atpower.Code.ToLower()))
                            {
                                throw new Exception("存在相同的权限Code:" + _atpower.Code + ",两个名称是:" + hasPower[_atpower.Title].Title + "/" + _atpower.Title);
                            }

                            hasPower[_atpower.Code] = _atpower;
                        }

                        //Api执行权限
                        if (attributesapipower != null && attributesapipower.Length == 1)
                        {
                            ApiPowerAttribute _atpower = attributesapipower[0] as ApiPowerAttribute;
                            //权限编号
                            _atpower.Code = areaStr + "_" + strcontroller + "_" + method.Name.ToLower()/*+"_"+httpMethodeStr*/;
                            //判断是否重复
                            if (hasApiPower.ContainsKey(_atpower.Code.ToLower()))
                            {
                                throw new Exception("存在相同的权限Code:" + _atpower.Code + ",两个名称是:" + hasPower[_atpower.Code].Title + "/" + _atpower.Title);
                            }
                            hasApiPower[_atpower.Code] = _atpower;
                        }
                      
                    }
                }

            //获取Power权限的菜单是否正确
            List<PowerAttribute> PowerList = new List<PowerAttribute>();
            foreach (var item in hasPower.Values)
            {
                if (!string.IsNullOrEmpty(item.MenuCode))
                {
                    if (!hasMenu.ContainsKey(item.MenuCode))
                    {
                        throw new Exception("菜单路径" + item.MenuCode.Replace('_','/') + "不存在!");
                    }
                }
                else
                {
                    PowerList.Add(item);
                }
            }
            //遍历
            foreach (var item in PowerList)
            {
                var c = item.Code.Split('_');
                if (c.Length < 1)
                {
                    continue;
                }
                foreach (var key in hasMenu.Keys)
                {
                    if (key.Contains( "admin_" + c[1] + "_"))
                    {
                        hasPower[item.Code].MenuCode = key;
                        break;
                    }
                }
            }
            if(hasMenu.Count>0)
            //将菜单存到数据库
                await  UpdateMeun();
            if (hasPower.Count > 0)
                //将权限保存到数据库
                await UpdatePower();
            if (hasApiPower.Count > 0)
                //将Api权限保存到数据库
                await UpdateApiPower();

           await InitAdminPermission();
        }
        //初始化超级管理员默认全部权限
        public static async Task InitAdminPermission()
        {
            var roleid = await SqlHelper.getstrasync("select top 1 id from sysrole where name='超级管理员'");
            var list_permission = await SqlHelper.GetDataListAsync<SysPermissionEntity>("select * from syspermission");
            var list_role_permission = await SqlHelper.GetDataListAsync<SysRolePermissionEntity>("select * from sysrolepermission");
            var list_add = new List<SysRolePermissionEntity>();

            foreach(var item in list_permission)
            {
                if (list_role_permission.Any(a => a.RoleId == roleid && a.PermissionId == item.Id)) continue;
                var data = new SysRolePermissionEntity()
                {
                    RoleId = roleid,
                    PermissionId = item.Id
                };

                list_add.Add(data);
            }
            await SqlHelper.addlistasync(list_add, "[SysRolePermission]");
        }

        /// <summary>
        /// 将菜单权限保存到数据
        /// </summary>
        public static async Task<List<SysPermissionEntity>> UpdateMeun()
        {
            try
            {
                //查询当前 存在的菜单(排除接口且平台为web)
                string sqlstr = "select * from SysPermission where type=0  and Platform=0";
                var dtmenu = await SqlHelper.getdatalistasync<SysPermissionEntity>(sqlstr) as List<SysPermissionEntity>;//系统数据库已存在的所有系统菜单
                List<object> menus = new List<object>();
                sqlstr = @"INSERT INTO [SysPermission]
                       ([Id]
                       ,[Name]
                       ,[Code]
                       ,[Path]
                       ,[Icon]
                       ,[Sort]
                       ,[CreateTime]
                       ,[Type]
                       ,[Platform]
                       ,[Remarks]
                       ,[Enabled]
                       ,[ParentId])
                 VALUES(@0,@1,@2,@3,@4,@5,@6,@7,@8,@9,@10,@11)";
                string updatesql = "update SysPermission set Path=@0,name=@1 where Code=@2 and Platform=0";

                //查询web端菜单code=1_1 的菜单的id
                var topId = await SqlHelper.getstrasync("select id from SysPermission where code=@0 and Platform=0 ", null, "1_1");
                if (topId.IsNull()) throw new Exception("请先配置code为 1_1 的内置菜单");
                var maxSort = await SqlHelper.getintasync("select max(sort) from [SysPermission] where type=0 and Platform=0");
                foreach (MenuAttribute menu in hasMenu.Values)
                {
                    menus.Add(menu.Code);
                    maxSort++;
                    //找到当前菜单的最大排序
                    if (!dtmenu.Exists(n => n.Code == menu.Code))
                    {
                        //插入
                        await SqlHelper.executeasync( sqlstr,GuidHelper.NewSequentialGuid(SequentialGuidType.SequentialAtEnd).To_String(),menu.Title,menu.Code,menu.MenuUrl, "el-icon-s-platform", maxSort,DateTime.Now,0,0,"代码生成的菜单",1,topId);
                    }
                    else if (dtmenu.Exists(n => n.Code == menu.Code)
                        || dtmenu.Exists(n => n.Name == menu.Title)
                        || dtmenu.Exists(n => n.Path == menu.MenuUrl))
                    {
                        await SqlHelper.executeasync(updatesql, menu.MenuUrl, menu.Title, menu.Code);
                    }
                }
                //删除 不要的菜单
              // await SqlHelper.excutenotinasync("delete from  SysPermission where type=0  and Platform=0 and layer<>0", "code", menus);
                return dtmenu;
            }
            catch (Exception err)
            {
                throw err;
            }
        }
        /// <summary>
        /// 将接口权限保存到数据库
        /// </summary>
        /// <returns></returns>
        public static async Task UpdatePower()
        {
            try
            {
                //查询接口权限 排除app接口
                string sqlstr = "select * from SysPermission where type=1 and  Platform=0 ";
                var dtpower = await SqlHelper.getdatalistasync<SysPermissionEntity>(sqlstr) as List<SysPermissionEntity>;
                List<object> powers = new List<object>();
                sqlstr = @"INSERT INTO [SysPermission]
                       ([Id]
                       ,[Name]
                       ,[Code]
                       ,[Sort]
                       ,[CreateTime]
                       ,[Type]
                       ,[Platform]
                       ,[Remarks]
                       ,[Enabled],ParentId
                       )
                 VALUES(@0,@1,@2,@3,@4,@5,@6,@7,@8,@9)";
                string updatesql = "update SysPermission set Name=@0,ParentId=@1 where code=@2 and Platform=0";
                var maxSort = await SqlHelper.getintasync("select max(sort) from [SysPermission] where type=1 and  Platform=0");

                foreach (PowerAttribute power in hasPower.Values)
                {
                    //查询出对应菜单code相同的菜单id
                    var parentid = await SqlHelper.getstrasync("select id from syspermission where code=@0", null, power.MenuCode);
                    powers.Add(power.Code);
                    maxSort++;
                    if (!dtpower.Exists(n => n.Code == power.Code))
                    {
                        await SqlHelper.executeasync(sqlstr,GuidHelper.NewSequentialGuid(SequentialGuidType.SequentialAtEnd).To_String(),power.Title,power.Code,maxSort,DateTime.Now,1,0,"代码生成的接口",1,parentid);
                    }
                    else if (dtpower.Exists(n => n.Code == power.Code))
                    {
                        await SqlHelper.executeasync(updatesql,power.Title,parentid,power.Code);
                    }                                     
                }
                await SqlHelper.excutenotinasync("delete from SysPermission where type=1  and Platform=0", "code", powers);

            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 将app接口保存到数据库
        /// </summary>
        /// <returns></returns>
        public static async Task UpdateApiPower()
        {
            try
            {
                //查询接口权限 排除web接口
                string sqlstr = "select * from SysPermission where type=1 and  Platform=1 ";
                var dtpower = await SqlHelper.getdatalistasync<SysPermissionEntity>(sqlstr) as List<SysPermissionEntity>;
                List<object> powers = new List<object>();
                sqlstr = @"INSERT INTO [SysPermission]
                       ([Id]
                       ,[Name]
                       ,[Code]
                       ,[Sort]
                       ,[CreateTime]
                       ,[Type]
                       ,[Platform]
                       ,[Remarks]
                       ,[Enabled])
                 VALUES(@0,@1,@2,@3,@4,@5,@6,@7,@8)";
                string updatesql = "update SysPermission set Name=@0 where code=@1 and Platform=1";
                var maxSort = await SqlHelper.getintasync("select max(sort) from [SysPermission] where type=1 and  Platform=1");
                foreach (ApiPowerAttribute power in hasApiPower.Values)
                {
                    powers.Add(power.Code);
                    maxSort++;
                    if (!dtpower.Exists(n => n.Code == power.Code))
                    {
                        await SqlHelper.executeasync(sqlstr, GuidHelper.NewSequentialGuid(SequentialGuidType.SequentialAtEnd).To_String(), power.Title, power.Code, maxSort, DateTime.Now, 1, 1, "代码生成的app接口", 1);
                    }
                    else if (dtpower.Exists(n => n.Code == power.Code))
                    {
                        await SqlHelper.executeasync(updatesql, power.Title, power.Code);
                    }
                }
                await SqlHelper.excutenotinasync("delete from SysPermission where type=1  and Platform=1", "code", powers);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
